﻿using com.youzu.got.protocol;
using System;
using UnityEngine;
using WorldMapBase;
using WorldMapBase.Tile.Pool;
using XLua;
using Yoozoo.Extension;
using Yoozoo.Gta.Common;
using Yoozoo.Mars.Got;
using Yoozoo.Mars.Got.SpriteAnim;
using Object = UnityEngine.Object;

namespace Yoozoo.Gameplay.RTS
{
    public class ArmyManager
    {
        public static SpriteParticleSystemManager SpriteParticleSystemManager;
        private static ArmyManager _instance;
        private RTSBattleEffectManager _battleEffectManager;
        private RTSClassPoolManager _classManager;
        private GameObject _drawLineToolObj;
        private Action _onLoadOver;
        private GameObject _rtsArmyRoot;
        private RTSMono _rtsMono;
        public ElementManager ElementManager;
        public HudManager HudManager;
        public MarchManager MarchManager;
        public static bool EnableRtsUnitTest = false;
        public static bool IsDebug = true;
        public static bool IsChasingDebug = false;
        public static bool IsDebugMarch = false;
        public static bool IsDebugSpriteLoading = false;
        public static bool NeverCheckSimpleMode = false;
        
        public ArmyManager()
        {
            //Debug.Log("创建一个ArmyManager");
            _instance = this;
            RTSQualityHelper.Initialize();
            RTSLuaCallCSharpManager.InitRtsUnitTest();
        }

        public static ArmyManager Instance => _instance;

        public RTSResourceManager ResourceManager { private set; get; }

        public void Initialize(Transform root)
        {
            _rtsArmyRoot = new GameObject("RTS_Army");
            _rtsArmyRoot.transform.parent = root;
            var spriteParticleSysGo = new GameObject("SpriteParticleSysGO");
            spriteParticleSysGo.transform.parent = _rtsArmyRoot.transform;
            //BattleFormationHelper.InitOffsets();
            InitClass();
            InitDrawLineTools();
            InitManager(spriteParticleSysGo);
            MarchManager.RegisterNonResourceReliableTasks();
            _rtsMono = _rtsArmyRoot.AddComponent<RTSMono>();
            //_rtsTest = _rtsArmyRoot.AddComponent<RTSTest>();
            MemoryPoolMgr.Instance.Fill();
        }
        
        

        public void PreloadResourceConfig(LuaTable resourceConfig, LuaTable resourcePoolConfig)
        {
            ResourceManager.PreloadResourceConfig(resourceConfig, resourcePoolConfig);
        }

        //public void LoadRes(Action onLoadOver)
        //{
        //    _onLoadOver = onLoadOver;
        //    ResourceManager.LoadBattlePrefabs(() =>
        //    {
        //        ResourceManager.LoadSoldiers(OnResourceReady);
        //    });
        //}

        public RTSResourceManager GetRtsResourceManager()
        {
            return ResourceManager;
        }

        public void Dispose()
        {
            if (_rtsMono != null)
            {
                _rtsMono.Dispose();
                Object.Destroy(_rtsMono);
                _rtsMono = null;
            }

            if (ElementManager != null)
            {
                ElementManager.Dispose();
                ElementManager = null;
            }

            if (MarchManager != null)
            {
                MarchManager.Dispose();
                MarchManager = null;
            }

            if (HudManager != null)
            {
                HudManager.Dispose();
                HudManager = null;
            }

            if (_battleEffectManager != null)
            {
                _battleEffectManager?.Dispose();
                _battleEffectManager = null;
            }

            if (ResourceManager != null)
            {
                ResourceManager.Dispose();
                ResourceManager = null;
            }

            if (_drawLineToolObj != null)
            {
                Object.DestroyImmediate(_drawLineToolObj);
                _drawLineToolObj = null;
            }

            if (SpriteParticleSystemManager)
            {
                Object.Destroy(SpriteParticleSystemManager.gameObject);
                SpriteParticleSystemManager = null;
            }

            if (_rtsArmyRoot)
            {
                Object.Destroy(_rtsArmyRoot);
                _rtsArmyRoot = null;
            }

            if (_classManager != null)
            {
                _classManager?.Destroy();
                _classManager = null;
            }

            if (DrawLineTool.GetInstance())
            {
                DrawLineTool.GetInstance().Dispose();
                drawLineTool = null;
                isDrawLineCameraBinded = false;
            }

            _instance = null;
        }

        public static void TryLoadResource(int id)
        {
            _instance.ResourceManager.TryLoadResource(id);
        }

        public static GameObject GetResourceById(int id, bool isForceGet = false,Action<GameObject> action = null)
        {
            return _instance.ResourceManager.GetResourceById(id, isForceGet,action);
        }

        public static void RecoverResourceById(int id, GameObject obj)
        {
            if (obj)
            {
                if (_instance != null && _instance.ResourceManager != null)
                {
                    _instance.ResourceManager.RecoverResourceById(id, obj);
                }
                else
                {
                    GameObject.Destroy(obj);
                }
            }
        }

        public static GameObject GetEffectById(int id, bool isRelatedToSelf)
        {
            bool isOverloaded = RTSQualityHelper.CheckIsEffectOverloaded(isRelatedToSelf);
            if (isOverloaded)
            {
                return null;
            }

            if (isRelatedToSelf)
            {
                RTSQualityHelper.SelfEffectUsingCount++;
            }
            else
            {
                RTSQualityHelper.OtherEffectUsingCount++;
            }
            return _instance.ResourceManager.GetResourceById(id);
        }

        public static void RecoverEffectById(int id, GameObject obj, bool isRelatedToSelf)
        {
            _instance.ResourceManager.RecoverResourceById(id, obj);
            if (isRelatedToSelf)
            {
                RTSQualityHelper.SelfEffectUsingCount--;
            }
            else
            {
                RTSQualityHelper.OtherEffectUsingCount--;
            }
        }

        public static void PlaySpriteAnimator(AnimSprite sprite, SPRITE_ACTION_ENUM action)
        {
            SpriteParticleSystemManager.PlayActionAnimation(sprite, action);
        }

        public static AnimSprite[] GetSoldierSprite(string modelName, int count, int team)
        {
            var creator = SpriteParticleSystemManager.GetSpriteCreatorByName(modelName + team);
            return SpriteParticleSystemManager.CreateAnimSprites(creator, count);
        }

        private Action _action;
        public static void LoadAndCreateSoldierSprite(string modelName, int team,Action<AnimSpriteCreator> onloadOver)
        {
            RTSSpriteManager.Inst.LoadSingleSoldierRes(modelName,onloadOver);
        }
        public static AnimSprite GetSoldierSprite(string modelName, int team)
        {
            var creator = SpriteParticleSystemManager.GetSpriteCreatorByOriginNameAndTeam(modelName, team);
            if (creator == null)
            {
#if DEVELOPMENT_BUILD || UNITY_EDITOR
                Debug.LogError("序列帧找不到" + modelName + " " + team);
#endif
            }
            //Profiler.BeginSample("CreateAnimSprite");
            var animSprite = SpriteParticleSystemManager.CreateAnimSprite(creator);
            //Profiler.EndSample();
            return animSprite;
        }
        public static AnimSprite GetSoldierSprite(AnimSpriteCreator creator)
        {
            var animSprite = SpriteParticleSystemManager.CreateAnimSprite(creator);
            return animSprite;
        }
        /// <summary>
        /// 返回精灵创造器，有可能返回为空
        /// </summary>
        /// <param name="modelName"></param>
        /// <param name="team"></param>
        /// <returns></returns>
        public static AnimSpriteCreator GetSpriteCreatorByOriginNameAndTeam(string modelName, int team)
        {
            var creator = SpriteParticleSystemManager.GetSpriteCreatorByOriginNameAndTeam(modelName, team);
            return creator;
        }

        public static float GetSoldierSpriteCreatorScale(string creatorName)
        {
            var creator = SpriteParticleSystemManager.GetSpriteCreatorByName(creatorName);
            if (creator == null || creator.SizeOffset == 0)
            {
                return 1;
            }
            return creator.SizeOffset;
        }

        public static AnimSpriteCreator GetCreator(string name)
        {
            return SpriteParticleSystemManager.GetSpriteCreatorByName(name + "0");
        }


        public static int RemoveSprite(AnimSprite sprite)
        {
            return SpriteParticleSystemManager.RemoveSprite(sprite);
        }

        public static void RemoveModel(IModel model)
        {
            _instance.ResourceManager.RemoveModel(model);
        }

        public static IModel GetModel(int index)
        {
            return _instance.ResourceManager.GetModel(index);
        }


        public static IModel GetModel(string modelName)
        {
            return _instance.ResourceManager.GetModel(modelName);
        }

        public void ShakeScreen()
        {
            _rtsMono.ShakeScreen();
        }

        public void StopShakeScreen()
        {
            _rtsMono.StopShakeScreen();
        }

        private void InitManager(GameObject spriteParticleSysGo)
        {
            ResidentHandler.Inst.GetFunction("G_MarchManager.InitQualityChange").Action();
            RTSSpriteHelper outerCitySpriteHelper = new RTSSpriteHelper();
            SpriteParticleSystemManager = spriteParticleSysGo.AddComponent<SpriteParticleSystemManager>();
            ResourceManager = new RTSResourceManager();
            ResourceManager.Init(PoolCollectionManager.GetInstance("PoolCollectionManager").transform);
            _battleEffectManager = new RTSBattleEffectManager();
            _battleEffectManager.Init();
            MarchManager = new MarchManager();
            ElementManager = new ElementManager();
            HudManager = new HudManager();
            SpriteParticleSystemManager.InitManager(outerCitySpriteHelper);
        }

        public static Action<int, int, string> loadingCallBack;
        private int needLoadPartCount = 4;
        public void StartLoadResource(Action<int, int, string> _loadingCallBack)
        {
            loadingCallBack = _loadingCallBack;
            needLoadPartCount = 5;
            HudManager.InitAndLoadHudPrefab(_rtsArmyRoot.transform, CheckIsResourceAllReady);
            SpriteParticleSystemManager.Load(CheckIsResourceAllReady);
            ResourceManager.LoadBattlePrefabs(CheckIsResourceAllReady);
            ResourceManager.LoadSoldiers(CheckIsResourceAllReady);
        }

        private void CheckIsResourceAllReady()
        {
            needLoadPartCount--;
            if (needLoadPartCount == 0)
            {
                loadingCallBack = null;
                SquareDataManager.Instance.InitSpriteData(SpriteParticleSystemManager.GetCreators());
                ResidentHandler.Inst.GetFunction("G_MarchManager.Init").Action();
                ResidentHandler.Inst.GetFunction("G_CityHelper.initCommonSpriteManager").Action();
            }
        }

        private bool isDrawLineCameraBinded = false;
        private DrawLineTool drawLineTool;
        
        public void InitDrawLineTools()
        {
            // 画线工具

            //TODO:drawlineTool初始化要放到这里么？PVE也在用
            DrawLineTool drawLineTool = DrawLineTool.GetInstance();
            if (!drawLineTool.IsInitialized())
            {
                drawLineTool.Initialize();
            }
            drawLineTool.SetHeight(GlobalValue.PathLineHeight);
            isDrawLineCameraBinded = false;
            if (WorldCameraManager.mainCamera)
            {
                drawLineTool.SetFollowTarget(WorldCameraManager.mainCamera.transform);
                isDrawLineCameraBinded = true;
            }
            drawLineTool.materialType = 0;
            drawLineTool.LINE_WIDTH = 0.08f;

            this.drawLineTool = drawLineTool;
            _drawLineToolObj = drawLineTool.gameObject;
        }
        
        public void OnWorldCameraReady()
        {
            CheckIsResourceAllReady(); // 相机要初始化完成
            if (!isDrawLineCameraBinded && drawLineTool != null)
            {
                drawLineTool.SetFollowTarget(WorldCameraManager.mainCamera.transform);
                isDrawLineCameraBinded = true;
            }
            MarchManager.Instance.OnWorldCameraReady();
        }

        private void OnResourceReady()
        {
            _onLoadOver?.Invoke();
        }

        private void InitClass()
        {
            _classManager = new RTSClassPoolManager();
            _classManager.InitClassPool();
        }

        public bool IsInSandBox = false;
        public void EnterSandBox()
        {
            IsInSandBox = true;
            MarchManager?.OnEnterSandBox();
        }

        public void LeaveSandBox()
        {
            MarchManager?.OnLeaveSandBox();
            IsInSandBox = false;
        }

        public bool CanPlayAudio(int sourceTeam,int targetTeam = -1)
        {
            bool isSelf = sourceTeam == 0 || targetTeam == 0;
            return IsInSandBox || isSelf;
        }

        /// <summary>
        ///是否是自定义的头像
        /// 如: 侦察和获取新兵的那个部队,头像实际上是自定义的灰色
        /// </summary>
        /// <param name="clientMarchType"></param>
        /// <returns></returns>
        public bool IsCustomHudMarchType(EClientMarchType clientMarchType)
        {
            if (clientMarchType == EClientMarchType.Rescue || 
                clientMarchType == EClientMarchType.Scout || 
                clientMarchType == EClientMarchType.Truck ||
                clientMarchType == EClientMarchType.Train)
            {
                return true;
            }

            return false;
        }

        private float cameraRotation = 45;

        public void SetCameraRotation(float rotation)
        {
            cameraRotation = rotation;
            SpriteParticleSystemManager.SetCameraRotation(rotation);
            if (FlyTextManager.FlyTextRoot)
            {
                FlyTextManager.FlyTextRoot.transform.SetLocalRotationY(ArmyManager.Instance.CameraRotation);
            }
        }
        
        public float CameraRotation => cameraRotation;
    }
}
